package com.backend.serializer;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.Objects;

@Slf4j
public class BigDecimalSerializer extends JsonSerializer {

  private final static int MAX_BIG_DECIMAL_SCALE = 9999;

  @Override
  public void serialize(Object object, JsonGenerator gen, SerializerProvider provider)
      throws IOException {
    if (Objects.nonNull(object) && object instanceof BigDecimal) {
      BigDecimal value = (BigDecimal) object;
      // 从com.fasterxml.jackson.databind.ser.std.NumberSerializer.BigDecimalAsStringSerializer拷贝 24-Aug-2016, tatu: [core#315] prevent possible DoS vector, so we need this
      if (!_verifyBigDecimalRange(value)) {
        // ... but wouldn't it be nice to trigger error via generator? Alas,
        // no method to do that. So we'll do...
        final String errorMsg = String.format(
            "Attempt to write plain `java.math.BigDecimal` (see JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN) with illegal scale (%d): needs to be between [-%d, %d]",
            value.scale(), MAX_BIG_DECIMAL_SCALE, MAX_BIG_DECIMAL_SCALE);
        provider.reportMappingProblem(errorMsg);
      }
      BigDecimal newValue = new BigDecimal(value.stripTrailingZeros().toPlainString());
      gen.writeNumber(newValue);
    } else {
      gen.writeObjectRef(object);
    }
  }

  // 24-Aug-2016, tatu: [core#315] prevent possible DoS vector, so we need this
  private boolean _verifyBigDecimalRange(BigDecimal value) {
    int scale = value.scale();
    return ((scale >= -MAX_BIG_DECIMAL_SCALE) && (scale <= MAX_BIG_DECIMAL_SCALE));
  }
}
